/*
    项目中的一些琐碎功能
    1. 简单日志
    2. json的序列化和反序列化
    3. uuid生成
*/

#pragma once
#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <atomic>
#include <iomanip>
#include <chrono>
#include <random>
#include <jsoncpp/json/json.h>

namespace myrpc
{
    #define DEBUG 0
    #define INFO 1
    #define ERROR 2

    #define DEBUG_STR "DEBUG"
    #define INFO_STR "INFO"
    #define ERROR_STR "ERROR"

    #define DEFAULT_LEVEL DEBUG

    //日志宏
    #define LOG(level_str, level_int, format, ...)\
    {\
        if(level_int >= DEFAULT_LEVEL)\
        {\
            time_t t = time(nullptr);\
            struct tm* pt = localtime(&t);\
            char time[50] = {0};\
            strftime(time, 49, "%Y-%m-%d %T", pt);\
            printf("[" level_str "][%s][%s:%d] " format "\n", time, __FILE__, __LINE__, ##__VA_ARGS__);\
        }\
    }

    #define DLOG(format, ...) LOG(DEBUG_STR, DEBUG, format, ##__VA_ARGS__)
    #define ILOG(format, ...) LOG(INFO_STR, INFO, format, ##__VA_ARGS__)
    #define ELOG(format, ...) LOG(ERROR_STR, ERROR, format, ##__VA_ARGS__)

    //Json序列化和反序列化
    class JSON
    {
    public:
        //json序列化
        static std::string serialize(const Json::Value& val)
        {
            std::stringstream ss;

            Json::StreamWriterBuilder swb;

            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            sw->write(val, &ss);

            return ss.str();
        }

        //反序列化
        static Json::Value unserialize(const std::string& str)
        {
            Json::Value ret;

            Json::CharReaderBuilder crb;

            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            cr->parse(str.c_str(), str.c_str() + str.size(), &ret, nullptr);
            return ret;
        }
    };

    //uuid生成
    class UUID
    {
    public:
        static std::string uuid()
        {
            std::stringstream ss;

            std::random_device rd;
            std::mt19937 generator(rd());
            std::uniform_int_distribution<int> distribution(0, 255);

            //生成8个随机数
            for(int i = 0; i < 8; i++)
            {
                if(i == 4 || i == 6) ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";

            //生成一个8字节序号
            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for(int i = 7; i >= 0; i--)
            {
                if(i == 5) ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xff);
            }
            return ss.str();
        }
    };
}
